package com.meida.module.file.provider.service.impl;

import cn.hutool.core.map.MapUtil;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.meida.common.configuration.OpenCommonProperties;
import com.meida.common.constants.QueueConstants;
import com.meida.common.constants.SettingConstant;
import com.meida.common.mybatis.base.service.impl.BaseServiceImpl;
import com.meida.common.base.entity.EntityMap;
import com.meida.common.mybatis.model.ResultBody;
import com.meida.common.mybatis.query.CriteriaQuery;
import com.meida.common.utils.ApiAssert;
import com.meida.common.base.utils.FlymeUtils;
import com.meida.module.file.client.entity.SysFile;
import com.meida.module.file.client.vo.OssSetting;
import com.meida.module.file.provider.mapper.SysFileMapper;
import com.meida.module.file.provider.oss.AliOssUtil;
import com.meida.module.file.provider.oss.FileUtil;
import com.meida.module.file.provider.service.SysFileService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * 文件表 服务实现类
 *
 * @author flyme
 * @date 2019-06-03
 */
@Service
@Transactional(rollbackFor = Exception.class)
public class SysFileServiceImpl extends BaseServiceImpl<SysFileMapper, SysFile> implements SysFileService {
    @Autowired
    private OpenCommonProperties openCommonProperties;
    @Autowired
    private FileUtil fileUtil;

    @Autowired
    private AliOssUtil aliOssUtil;

    @Override
    @Transactional(propagation = Propagation.SUPPORTS, readOnly = true)
    public ResultBody getFileList(Long busId, String busType) {
        CriteriaQuery<SysFile> cq = new CriteriaQuery<SysFile>(SysFile.class);
        cq.select("file.*");
        cq.select("CONCAT('" + openCommonProperties.getFileServerAddr() + "/1/',file.fileId) url");
        cq.select("CONCAT('" + openCommonProperties.getFileServerAddr() + "/2/',file.fileId) smallUrl");
        cq.eq("busId", busId);
        cq.eq("busType", busType);
        return baseList(cq);
    }

    @Override
    @Transactional(propagation = Propagation.SUPPORTS, readOnly = true)
    public List<EntityMap> selectFileList(Long busId, Class cls) {
        return selectFileListByFileType(busId, cls, null);
    }

    @Override
    public List<EntityMap> selectFileListByFileType(Long busId, Class cls, String fileType) {
        return selectFileListByFileType(busId, cls.getSimpleName(), fileType);
    }

    @Override
    public List<EntityMap> selectFileListByFileType(Long busId, String clsName, String fileType) {
        CriteriaQuery<EntityMap> cq = new CriteriaQuery(SysFile.class);
        String used = redisUtils.getConfig(SettingConstant.OSS_USED);
        if (used.equals(SettingConstant.ALI_OSS)) {
            cq.select(SysFile.class, "ossPath url");
        } else {
            cq.select(SysFile.class, "fileUrl url");
        }
        cq.select(SysFile.class, "fileId", "fileId uid", "fileName name", "smallOssPath", "ossPath");
        cq.eq("busId", busId);
        if (FlymeUtils.isNotEmpty(fileType)) {
            cq.like("fileType", fileType);
        }
        cq.eq("busType", clsName);
        ResultBody<List<EntityMap>> resultBody = baseList(cq);
        if (resultBody.isOk()) {
            return resultBody.getData();
        }
        return null;
    }

    @Override
    @Transactional(propagation = Propagation.SUPPORTS, readOnly = true)
    public List<EntityMap> selectDeleteFileList(Long[] fileIds, Long busId, String busType) {
        CriteriaQuery<EntityMap> cq = new CriteriaQuery(SysFile.class);
        if (FlymeUtils.isNotEmpty(fileIds)) {
            cq.select(SysFile.class, "fileId", "fileId uid", "localPath", "fileUrl", "ossPath", "smallOssPath");
            cq.in(true, "fileId", fileIds);
            ResultBody<List<EntityMap>> resultBody = baseList(cq);
            return resultBody.getData();
        } else {
            return null;
        }

    }

    @Override
    public boolean setBusIdAndBusType(Long busId, String busType, String fileIds) {
        String[] split = fileIds.split(",");
        ArrayList<Long> longIds = new ArrayList<>();
        for (String fileId : split) {
            Long id = Long.valueOf(fileId);
            longIds.add(id);
        }
        CriteriaQuery<SysFile> q = new CriteriaQuery<SysFile>(SysFile.class);
        List<SysFile> files = list(q.in("fileId", longIds));
        for (SysFile file : files) {
            file.setBusId(busId).setBusType(busType);
        }
        return updateBatchById(files);
    }

    @Override
    public Map<String, Object> upload(MultipartFile file, Long busId, String busType, String base64Img) {
        //文件类型
        String used = redisUtils.getConfig(SettingConstant.OSS_USED);
        ApiAssert.isNotEmpty("未配置文件上传", used);
        String result;
        String fKey = FlymeUtils.renamePic(file.getOriginalFilename());
        SysFile f = new SysFile();
        String fileUrl = "";
        //申领文件id
        Long fileId = IdWorker.getId();
        f.setFileId(fileId);
        f.setFileName(file.getOriginalFilename());
        f.setFileSize(file.getSize());
        f.setBusId(busId);
        f.setBusType(busType);
        f.setFileType(file.getContentType());
        f.setFileKey(fKey);
        Boolean useOss = false;
        String ossPath = "";
        String ossSmallPath = "";
        // 上传至第三方云服务或服务器
        InputStream inputStream = FileUtil.getInputStream(file);
        if (FlymeUtils.isNotEmpty(inputStream)) {
            String fileType = FileUtil.getExtend(f.getFileName(), "");
            //本地上传
            OssSetting os = fileUtil.getOssSetting();
            if (FlymeUtils.isNotEmpty(base64Img)) {
                result = fileUtil.cutImageByBase64(file, fKey, f, base64Img);
            } else {
                result = fileUtil.localUpload(file, fKey, f);
            }
            if (FileUtil.isPicture(fileType)) {
                fileUrl = os.getHttp() + os.getEndpoint() + "/image/" + fileId;
            } else {
                fileUrl = os.getHttp() + os.getEndpoint() + "/" + fileId;
            }
            f.setFileUrl(fileUrl);
            f.setLocalPath(result);
            f.setStoreType(SettingConstant.OSS_LOCAL);
            if (used.equals(SettingConstant.ALI_OSS)) {
                OssSetting aliOs = aliOssUtil.getOssSetting();
                ossPath = aliOs.getHttp() + aliOs.getBucket() + "." + aliOs.getEndpoint() + "/" + fKey;
                ossSmallPath = aliOs.getHttp() + aliOs.getBucket() + "." + aliOs.getEndpoint() + "/small_" + fKey;
                f.setStoreType(SettingConstant.OSS_ALI);
                f.setOssPath(ossPath);
                useOss = true;
                //使用OSS路径返回
                fileUrl = ossPath;
            }
            //保存图片到数据库
            this.save(f);
            if (useOss) {
                EntityMap ossMap = new EntityMap();
                ossMap.put("fileId", fileId);
                ossMap.put("filePath", f.getLocalPath());
                ossMap.put("smallPath", f.getSmallPath());
                ossMap.put("fKey", fKey);
                //异步上传文件到阿里云
                amqpTemplate.convertAndSend(QueueConstants.QUEUE_UPLOADOSS, ossMap);
            }
        }
        Map<String, Object> response = MapUtil.newHashMap();
        //返回前台路径
        response.put("url", fileUrl);
        response.put("ossPath", ossPath);
        response.put("ossSmallPath", ossSmallPath);
        response.put("useOss", useOss);
        response.put("uid", fileId);
        response.put("status", "done");
        response.put("name", f.getFileName());
        return response;
    }

}
